package THU.hxdExp;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

public class FileProcessor {

	private Map<String, Integer> sessionNums = new HashMap<>();

	public void readSession(String filename) throws Exception {
		BufferedReader reader = new BufferedReader(new FileReader(filename));
		String[] data;
		String line = reader.readLine(); //  [?1034h
		line = reader.readLine(); //  session_id | client | command | coordinator | duration | parameters | request | started_at
		line = reader.readLine(); // ------------+--------+---------+-------------+----------+------------+---------+------------
		while ((line = reader.readLine()) != null) {
			data = line.split("\\|");
			if (data.length < 8)
				continue;

			String session = data[0].trim();
			if (sessionNums.containsKey(session)) {
				int num = sessionNums.get(session);
				sessionNums.put(session, num + 1);
			} else {
				sessionNums.put(session, 1);
			}
		}
		reader.close();
		System.out.println("Session num : " + sessionNums.size());
	}

	private Map<String, Integer> basicEvents = new HashMap<>();
	private Map<String, Character> eventDirectory = new HashMap<>();
	private Map<String, List<String>> sessionEvents = new HashMap<>();

	private Map<String, Integer> histogram = new TreeMap<>();

	public void readEvent(String filename) throws Exception {
		BufferedReader reader = new BufferedReader(new FileReader(filename));
		String[] data;
		String line = reader.readLine(); //  [?1034h
		line = reader.readLine(); //  session_id | event_id | activity | source| source_elapsed | thread
		line = reader.readLine(); // ------------+----------+----------+-------+----------------+--------
		while ((line = reader.readLine()) != null) {
			data = line.split("\\|");
			if (data.length < 6)
				continue;

			String event = replaceNumWithX(data[2].trim());
			if (basicEvents.containsKey(event)) {
				int times = basicEvents.get(event) + 1;
				basicEvents.put(event, times);
			} else {
				int times = 1;
				basicEvents.put(event, times);
			}

			String session = data[0].trim();
			if (sessionEvents.containsKey(session)) {
				List<String> events = sessionEvents.get(session);
				events.add(event);
				sessionEvents.put(session, events);
			} else {
				List<String> events = new ArrayList<>();
				events.add(event);
				sessionEvents.put(session, events);
			}
		}
		reader.close();
	}

	public void printBasic() {
		for (Entry<String, Integer> basicEvent : basicEvents.entrySet()) {
			String event = basicEvent.getKey();
			Integer times = basicEvent.getValue();
			System.out.println(event + ", " + times);
		}
	}

	public void produceDirectory() {
		char eventSign = 'A';
		for (Entry<String, Integer> basicEvent : basicEvents.entrySet()) {
			String event = basicEvent.getKey();
			if (eventSign > 'Z' && eventSign < 'a')
				eventSign = 'a';
			eventDirectory.put(event, eventSign);
			eventSign++;
		}
	}

	public void produceHistogram() {
		for (Entry<String, List<String>> sessionEvent : sessionEvents.entrySet()) {
			String eventList = listToString(sessionEvent.getValue());
			if (histogram.containsKey(eventList)) {
				int times = histogram.get(eventList) + 1;
				histogram.put(eventList, times);
			} else {
				int times = 1;
				histogram.put(eventList, times);
			}
		}

		System.out.println("histogram size : " + histogram.size());
	}

	public void printHistogram() {
		List<Map.Entry<String, Integer>> entryList = new ArrayList<Map.Entry<String, Integer>>(histogram.entrySet());  
        Collections.sort(entryList, new MapValueComparator());
		for (int i = 0; i < entryList.size(); ++i) {
			String content = entryList.get(i).getKey();
			Integer times = entryList.get(i).getValue();
			System.out.println(content + ", " + times);
		}
	}
	
	public class MapValueComparator implements Comparator<Map.Entry<String, Integer>> {  
	    public int compare(Entry<String, Integer> me1, Entry<String, Integer> me2) {  
	        return -me1.getValue().compareTo(me2.getValue());  
	    }  
	}

	private String replaceNumWithX(String text) {
		String temp = text.replace('0', 'X');
		temp = temp.replace('1', 'X');
		temp = temp.replace('2', 'X');
		temp = temp.replace('3', 'X');
		temp = temp.replace('4', 'X');
		temp = temp.replace('5', 'X');
		temp = temp.replace('6', 'X');
		temp = temp.replace('7', 'X');
		temp = temp.replace('8', 'X');
		temp = temp.replace('9', 'X');

		return temp;
	}

	private String listToString(List<String> a) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < a.size(); ++i) {
			char eventSign = eventDirectory.get(a.get(i));
			sb.append(eventSign);
		}

		return sb.toString();
	}

	public static void main(String[] args) throws Exception {
		FileProcessor processor = new FileProcessor();
		
		// String sessionFile = "readSessions";
		String eventFile = "readEvents";

		// processor.readSession(sessionFile);

		processor.readEvent(eventFile);
		processor.produceDirectory();
		//processor.printBasic();
		processor.produceHistogram();
		processor.printHistogram();
	}
}
